package org.summerframework.core.util;

import org.apache.commons.lang3.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by shichao on 2016/11/28.
 *
 * <p>
 * 类似于jquery  class匹配
 */
public class ElementUtil {
    private Document document;
    private Element root;

    private ElementUtil() {
    }

    public ElementUtil(String path) throws DocumentException {
        this(new File(path));
    }

    public ElementUtil(File file) throws DocumentException {
        this(SAXReaderUtil.getInstance().read(file));
    }

    public ElementUtil(InputStream in) throws DocumentException {
        this(SAXReaderUtil.getInstance().read(in));
    }

    public ElementUtil(Document document) {
        this.document = document;
        this.root = this.document.getRootElement();
    }

    public List<Element> elements(String name) {
        return elements(root, name);
    }

    public static List<Element> elements(Element element, String name) {
        if (StringUtils.isNotBlank(name)) {
            List<String> list = Arrays.asList(name.split("\\."));

            if (list.isEmpty()) {
                list = new ArrayList<>();
                list.add(name);
            }

            for (int i = 0; i < list.size(); i++) {
                if (i == list.size() - 1) {
                    if (element != null)
                        return element.elements(list.get(i));
                } else {
                    element = getElement(element, list.get(i));
                }
            }
        }

        return null;
    }

    public Element element(String name) {
        return element(root, name);
    }

    public static Element element(Element element, String name) {
        if (StringUtils.isNotBlank(name)) {
            List<String> list = Arrays.asList(name.split("\\."));

            if (list.isEmpty()) {
                list = new ArrayList<>();
                list.add(name);
            }

            for (String str : list) {
                element = getElement(element, str);
            }
        }

        return element;
    }

    private static Element getElement(Element element, String name) {
        Matcher matcher = Pattern.compile("\\[(.*?)\\]").matcher(name);
        if (matcher.find()) {
            if (element != null) {
                String str = matcher.group(1);
                String[] strs = str.split("=");
                name = matcher.replaceAll("");

                List list = element.elements(name);

                for (Object o : list) {
                    if (o instanceof Element) {
                        Element e = element((Element) o, strs[0]);

                        if (strs.length == 1 && e != null) {
                            return ((Element) o);
                        } else if (strs.length == 2 && stringAreEquals(getValue((Element) o, strs[0]), strs[1])) {
                            return ((Element) o);
                        }
                    }
                }
            }
        } else {
            if (element != null) {
                return element.element(name);
            }
        }

        return null;
    }

    private static boolean stringAreEquals(String str1, String str2) {
        return str1 == null ? str2 == null : str1.equals(str2);
    }

    public static String attribute(Element element, String name) {
        if (element != null) {
            Attribute attribute = element.attribute(name);

            if (attribute != null) {
                return attribute.getStringValue();
            }
        }

        return null;
    }

    public String getValue(String name) {
        return getValue(root, name);
    }

    public static String getValue(Element element, String name) {
        Element tempElement = element(element, name);

        if (tempElement != null) {
            return tempElement.getStringValue();
        } else {
            int index = name.lastIndexOf(".");
            String lastName = name;

            if (index > -1) {
                String path = name.substring(0, index);
                lastName = name.substring(index + 1);
                tempElement = element(element, path);
            } else {
                tempElement = element;
            }


            if (tempElement != null) {
                return attribute(tempElement, lastName);
            }
        }

        return null;
    }

    public Document getDocument() {
        return document;
    }

    public Element getRoot() {
        return root;
    }
}
